#pragma once
#include <iostream>
#include <string>
// #include <>

const std::string spacesep = " ";
const std::string messagesep = "\n";

// 封装报头
// 因为添加报头需要算出有效载荷的长度，所以需要传数据，计算长度
std::string Encode(std::string &content)
{
    size_t len = content.size();
    std::string pakeage;
    pakeage += std::to_string(len);
    pakeage += messagesep;
    pakeage += content;
    pakeage += messagesep;

    return pakeage;
}


// 去报头
//"7"\n"10 + 10"\n   这个你没有包含最后的\n吗，就是7的长度，我刚刚数了下，没有包含
bool Decode(std::string &package, std::string* content)
{
    int pos = package.find(messagesep);
    if (pos == std::string::npos)
        return false;
    std::string len_str = package.substr(0, pos);
    int len = stoi(len_str);
    int len_total = len + pos + 2;
    if (len_total < package.size())
        return false;
    std::string contentval = package.substr(pos + 1, len);

    *content = contentval;
    package.erase(0, len_total);

    return true;
}

// // 去报头
// bool Decode(std::string &pakeage, std::string *content)
// {
//     size_t pos = pakeage.find(messagesep);
//     if (pos == std::string::npos) return false;
//     std::string str = pakeage.substr(0, pos);
//     size_t len_str = stoi(str);
//     size_t total_str = str.size() + len_str + 2;
//     // 发多少数据并不是由服务器决定的，而是由Tcp，所以数据可能不完整，我们需要判断一下，如果不完整直接丢弃即可
//     if (total_str < pakeage.size()) return false;
//     *content = pakeage.substr(pos + 1, len_str);

//     // 传入的数据可能不止一个完整的报文，去掉一个报头之后进行删除
//     pakeage.erase(0, total_str);

//     return true;
// }

class Request
{
public:
    Request()
    {
    }
    Request(const int &_x, const int &_y, const char &_op) : x(_x), y(_y), op(_op)
    {
    }
    // 序列化
    // "7"\n"10 + 20"\n
    bool serialize(std::string *out)
    {
        *out += std::to_string(x);
        *out += spacesep;
        *out += op;
        *out += spacesep;
        *out += std::to_string(y);

        return true;
    }

    // 反序列化
    // "10 + 20"
    bool Deserialize(const std::string &in)
    {
        size_t left = in.find(spacesep);
        if (left == std::string::npos) return false;
        std::string part_x = in.substr(0, left);
        size_t right = in.rfind(spacesep);
        if (right == std::string::npos) return false;
        if (right != left + 2) return false;
        std::string part_y = in.substr(right + 1);
        x = stoi(part_x);
        op = in[left + 1];
        y = stoi(part_y);

        return true;
    }

    ~Request()
    {
    }

public:
    int x;
    int y;
    char op;
};

class Response
{
public:
    Response()
    {
    }
    Response(int _result, int _code) : result(_result), code(_code)
    {
    }
    //  "result code"
    bool serialize(std::string *out)
    {
        std::string content = std::to_string(result);
        content += spacesep;
        content += std::to_string(code);

        *out = content;

        return true;
    }

    // 反序列化
    //  "result code"
    bool Deserialize(const std::string &in)
    {
        size_t pos = in.find(spacesep);
        if (pos == std::string::npos)
            return false;

        std::string left = in.substr(0, pos);
        std::string right = in.substr(pos + 1);

        result = stoi(left);
        code = stoi(right);

        return true;
    }

    void Printret()
    {
        std::cout << "result: " << result << " code: " << code << std::endl;
    }

    ~Response()
    {
    }

public:
    int result;
    int code;
};